`include "all_define.vh"

module licore_top#(
  parameter [31:0] BOOT_ADDR = 32'b0
) (
  input clk,
  input rst_n,
  output [31:0] imem_addr,
  input  [31:0] imem_inst,

  output        dmem_req,
  output        dmem_rwn,
  output [1:0]  dmem_size,
  output [31:0] dmem_addr,
  output [31:0] dmem_wdata,
  input         dmem_grant,
  input  [31:0] dmem_rdata
);

  wire        ctrl_if_stall;
  wire        ctrl_if_flush;
  wire        ctrl_if_jmp_ena;
  wire [31:0] ctrl_if_jmp_target;

  wire        ctrl_id_flush;
  wire        ctrl_id_stall;
  wire        ctrl_id_rs1_bypass_en;
  wire [31:0] ctrl_id_rs1_bypass_data;
  wire        ctrl_id_rs2_bypass_en;
  wire [31:0] ctrl_id_rs2_bypass_data;

  wire        ctrl_exe_flush;
  wire        ctrl_exe_stall;

  wire        id_jmp_req;
  wire [31:0] id_jmp_target;

  wire        id_rs1_bypass_vld;
  wire [4:0]  id_rs1_bypass;
  wire        id_rs2_bypass_vld;
  wire [4:0]  id_rs2_bypass;

  wire        exe_jmp_req;
  wire [31:0] exe_jmp_target;

  wire        exe_bypass_rd_vld;
  wire        exe_bypass_wait_load;
  wire [4:0]  exe_bypass_rd;
  wire [31:0] exe_bypass_rd_data;

  wire        mem_stall_req;

  wire [4:0]  mem_bypass_rd;
  wire        mem_bypass_rd_ena;
  wire [31:0] mem_bypass_rd_data;
  wire [31:0] mem_bypass_load_data;
  wire        mem_bypass_load_data_vld;

  wire        if_id_vld;
  wire [31:0] if_id_inst;
  wire [31:0] if_id_pc;

  wire        wb_id_rd_wena;
  wire [4:0]  wb_id_rd;
  wire [31:0] wb_id_rd_data;

  wire                        id_exe_vld;
  wire                        id_exe_is_lui;
  wire                        id_exe_is_bench;
  wire                        id_exe_is_jal;
  wire                        id_exe_is_jalr;
  wire [31:0]                 id_exe_bench_target;
  wire [31:0]                 id_exe_pc;
  wire [31:0]                 id_exe_pc_inc;
  wire                        id_exe_op1_is_pc;
  wire                        id_exe_op2_is_imm;
  wire                        id_exe_is_unsigned;
  wire [`ALU_TYPE_WIDTH-1:0]  id_exe_alu_type;
  wire [`ALU_OPSEL_WIDTH-1:0] id_exe_alu_opsel;
  wire [31:0]                 id_exe_imm_data;
  wire [31:0]                 id_exe_rs1_data;
  wire [31:0]                 id_exe_rs2_data;

  wire                        id_exe_mem_ena;
  wire [`MEM_DTYPE_WIDTH-1:0] id_exe_mem_dtype;
  wire                        id_exe_mem_rwn;

  wire                        id_exe_wb_ena;
  wire [4:0]                  id_exe_wb_rd;

  wire                        exe_mem_vld;
  wire                        exe_mem_opena;
  wire                        exe_mem_rwn;
  wire [`MEM_DTYPE_WIDTH-1:0] exe_mem_dtype;
  wire [31:0]                 exe_mem_addr;
  wire [31:0]                 exe_mem_datain;

  wire                        exe_mem_wb_ena;
  wire [4:0]                  exe_mem_wb_rd;
  wire [31:0]                 exe_mem_wb_rd_data;

  wire        mem_wb_vld;
  wire        mem_wb_is_opload;
  wire [4:0]  mem_wb_rd;
  wire [31:0] mem_wb_rd_data;
  wire [31:0] mem_wb_mrdata;

  core_ctrl core_ctrl_inst (
    .clk(clk),
    .rst_n(rst_n),

    .id_jmp_req(id_jmp_req),
    .id_jmp_target(id_jmp_target),
    .exe_jmp_req(exe_jmp_req),
    .exe_jmp_target(exe_jmp_target),

    .mem_stall_req(mem_stall_req),

    .id_rs1_bypass_vld(id_rs1_bypass_vld),
    .id_rs1_bypass(id_rs1_bypass),
    .id_rs2_bypass_vld(id_rs2_bypass_vld),
    .id_rs2_bypass(id_rs2_bypass),

    .exe_bypass_rd_vld(exe_bypass_rd_vld),
    .exe_bypass_wait_load(exe_bypass_wait_load),
    .exe_bypass_rd(exe_bypass_rd),
    .exe_bypass_rd_data(exe_bypass_rd_data),

    .mem_bypass_rd(mem_bypass_rd),
    .mem_bypass_rd_ena(mem_bypass_rd_ena),
    .mem_bypass_rd_data(mem_bypass_rd_data),
    .mem_bypass_load_data(mem_bypass_load_data),
    .mem_bypass_load_data_vld(mem_bypass_load_data_vld),

    .ctrl_id_rs1_bypass_en(ctrl_id_rs1_bypass_en),
    .ctrl_id_rs1_bypass_data(ctrl_id_rs1_bypass_data),
    .ctrl_id_rs2_bypass_en(ctrl_id_rs2_bypass_en),
    .ctrl_id_rs2_bypass_data(ctrl_id_rs2_bypass_data),

    .ctrl_if_jmp_ena(ctrl_if_jmp_ena),
    .ctrl_if_jmp_target(ctrl_if_jmp_target),

    .ctrl_if_stall(ctrl_if_stall),
    .ctrl_id_stall(ctrl_id_stall),
    .ctrl_exe_stall(ctrl_exe_stall),
    .ctrl_if_flush(ctrl_if_flush),
    .ctrl_id_flush(ctrl_id_flush),
    .ctrl_exe_flush(ctrl_exe_flush)
  );

  if_stage#(
    .BOOT_ADDR(BOOT_ADDR)
  ) if_stage_inst(
    .clk(clk),
    .rst_n(rst_n),

    .ctrl_if_stall(ctrl_if_stall),
    .ctrl_if_flush(ctrl_if_flush),
    .ctrl_if_jmp_ena(ctrl_if_jmp_ena),
    .ctrl_if_jmp_target(ctrl_if_jmp_target),

    .if_mem_addr(imem_addr),
    .if_mem_inst(imem_inst),

    .if_id_vld(if_id_vld),
    .if_id_inst(if_id_inst),
    .if_id_pc(if_id_pc)
  );

  id_stage id_stage_inst(
    .clk(clk),
    .rst_n(rst_n),

    .ctrl_id_flush(ctrl_id_flush),
    .ctrl_id_stall(ctrl_id_stall),
    .ctrl_id_rs1_bypass_en(ctrl_id_rs1_bypass_en),
    .ctrl_id_rs1_bypass_data(ctrl_id_rs1_bypass_data),
    .ctrl_id_rs2_bypass_en(ctrl_id_rs2_bypass_en),
    .ctrl_id_rs2_bypass_data(ctrl_id_rs2_bypass_data),

    .if_id_vld(if_id_vld),
    .if_id_inst(if_id_inst),
    .if_id_pc(if_id_pc),

    .wb_id_rd_wena(wb_id_rd_wena),
    .wb_id_rd(wb_id_rd),
    .wb_id_rd_data(wb_id_rd_data),

    .id_exe_vld(id_exe_vld),
    .id_exe_is_lui(id_exe_is_lui),
    .id_exe_is_bench(id_exe_is_bench),
    .id_exe_is_jal(id_exe_is_jal),
    .id_exe_is_jalr(id_exe_is_jalr),
    .id_exe_bench_target(id_exe_bench_target),
    .id_exe_pc(id_exe_pc),
    .id_exe_pc_inc(id_exe_pc_inc),
    .id_exe_op1_is_pc(id_exe_op1_is_pc),
    .id_exe_op2_is_imm(id_exe_op2_is_imm),
    .id_exe_is_unsigned(id_exe_is_unsigned),
    .id_exe_alu_type(id_exe_alu_type),
    .id_exe_alu_opsel(id_exe_alu_opsel),
    .id_exe_imm_data(id_exe_imm_data),
    .id_exe_rs1_data(id_exe_rs1_data),
    .id_exe_rs2_data(id_exe_rs2_data),

    .id_exe_mem_ena(id_exe_mem_ena),
    .id_exe_mem_dtype(id_exe_mem_dtype),
    .id_exe_mem_rwn(id_exe_mem_rwn),

    .id_exe_wb_ena(id_exe_wb_ena),
    .id_exe_wb_rd(id_exe_wb_rd),

    .id_jmp_req(id_jmp_req),
    .id_jmp_target(id_jmp_target),

    .id_rs1_bypass_vld(id_rs1_bypass_vld),
    .id_rs1_bypass(id_rs1_bypass),
    .id_rs2_bypass_vld(id_rs2_bypass_vld),
    .id_rs2_bypass(id_rs2_bypass)
  );

  exe_stage exe_stage_inst(
    .clk(clk),
    .rst_n(rst_n),

    .ctrl_exe_flush(ctrl_exe_flush),
    .ctrl_exe_stall(ctrl_exe_stall),

    .id_exe_vld(id_exe_vld),
    .id_exe_is_lui(id_exe_is_lui),
    .id_exe_is_bench(id_exe_is_bench),
    .id_exe_is_jal(id_exe_is_jal),
    .id_exe_is_jalr(id_exe_is_jalr),
    .id_exe_bench_target(id_exe_bench_target),
    .id_exe_pc(id_exe_pc),
    .id_exe_pc_inc(id_exe_pc_inc),
    .id_exe_op1_is_pc(id_exe_op1_is_pc),
    .id_exe_op2_is_imm(id_exe_op2_is_imm),
    .id_exe_is_unsigned(id_exe_is_unsigned),
    .id_exe_alu_type(id_exe_alu_type),
    .id_exe_alu_opsel(id_exe_alu_opsel),
    .id_exe_imm_data(id_exe_imm_data),
    .id_exe_rs1_data(id_exe_rs1_data),
    .id_exe_rs2_data(id_exe_rs2_data),

    .id_exe_mem_ena(id_exe_mem_ena),
    .id_exe_mem_dtype(id_exe_mem_dtype),
    .id_exe_mem_rwn(id_exe_mem_rwn),

    .id_exe_wb_ena(id_exe_wb_ena),
    .id_exe_wb_rd(id_exe_wb_rd),

    .exe_mem_vld(exe_mem_vld),
    .exe_mem_opena(exe_mem_opena),
    .exe_mem_rwn(exe_mem_rwn),
    .exe_mem_dtype(exe_mem_dtype),
    .exe_mem_addr(exe_mem_addr),
    .exe_mem_datain(exe_mem_datain),

    .exe_mem_wb_ena(exe_mem_wb_ena),
    .exe_mem_wb_rd(exe_mem_wb_rd),
    .exe_mem_wb_rd_data(exe_mem_wb_rd_data),

    .exe_jmp_req(exe_jmp_req),
    .exe_jmp_target(exe_jmp_target),

    .exe_bypass_rd_vld(exe_bypass_rd_vld),
    .exe_bypass_wait_load(exe_bypass_wait_load),
    .exe_bypass_rd(exe_bypass_rd),
    .exe_bypass_rd_data(exe_bypass_rd_data)
  );

  mem_stage mem_stage_inst (
    .clk(clk),
    .rst_n(rst_n),

    .exe_mem_vld(exe_mem_vld),
    .exe_mem_opena(exe_mem_opena),
    .exe_mem_rwn(exe_mem_rwn),
    .exe_mem_dtype(exe_mem_dtype),
    .exe_mem_addr(exe_mem_addr),
    .exe_mem_datain(exe_mem_datain),

    .exe_mem_wb_ena(exe_mem_wb_ena),
    .exe_mem_wb_rd(exe_mem_wb_rd),
    .exe_mem_wb_rd_data(exe_mem_wb_rd_data),

    .dmem_if_req(dmem_req),
    .dmem_if_rwn(dmem_rwn),
    .dmem_if_size(dmem_size),
    .dmem_if_addr(dmem_addr),
    .dmem_if_wdata(dmem_wdata),
    .dmem_if_grant(dmem_grant),
    .dmem_if_rdata(dmem_rdata),

    .mem_wb_vld(mem_wb_vld),
    .mem_wb_is_opload(mem_wb_is_opload),
    .mem_wb_rd(mem_wb_rd),
    .mem_wb_rd_data(mem_wb_rd_data),
    .mem_wb_mrdata(mem_wb_mrdata),

    .mem_stall_req(mem_stall_req),

    .mem_bypass_rd(mem_bypass_rd),
    .mem_bypass_rd_ena(mem_bypass_rd_ena),
    .mem_bypass_rd_data(mem_bypass_rd_data),
    .mem_bypass_load_data(mem_bypass_load_data),
    .mem_bypass_load_data_vld(mem_bypass_load_data_vld)
  );

  wb_stage wb_stage_inst (
    .clk(clk),
    .rst_n(rst_n),
    .mem_wb_vld(mem_wb_vld),
    .mem_wb_is_opload(mem_wb_is_opload),
    .mem_wb_rd(mem_wb_rd),
    .mem_wb_rd_data(mem_wb_rd_data),
    .mem_wb_mrdata(mem_wb_mrdata),

    .wb_id_rd_wena(wb_id_rd_wena),
    .wb_id_rd(wb_id_rd),
    .wb_id_rd_data(wb_id_rd_data)
  );

endmodule

